/*
 * UserFrame.java
 *
 * Created on 21.nov.2011, 17:11:09
 */
package no.uials.distsys;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Toolkit;
import java.rmi.RemoteException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static javax.swing.JOptionPane.*;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author Martinsen
 */
public class UserFrame extends javax.swing.JFrame {
    private Login login;
    private UserService service;
    private User user;
    private Point p;
    private ArrayList<Article> search = new ArrayList<>();
    private Map<String, OrderLine> lines = new HashMap<>();
    private ChangePwdDialog chPwd;
    private DecimalFormat decimalFormat;
    private DefaultTableModel articleTableModel = new DefaultTableModel(new String[] {"ID", "Name", "Price", "Stock", "Position"}, 0) {
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    };
    private DefaultTableModel currentOrderTableModel = new DefaultTableModel(new String[] {"ID", "Name", "Price", "Units", "Total"}, 0) {
        boolean[] editable = new boolean[] {false, false, false, true, false};
        public boolean isCellEditable(int row, int column) {
            return editable[column];
        }
    };
    private DefaultTableModel previousOrdersTableModel = new DefaultTableModel(new String[] {"#", "User", "Date", "Units", "Total"}, 0) {
        public boolean isCellEditable(int row, int column) {
            return false;
        }
    };

    /** Creates new form UserFrame */
    public UserFrame(Login login, UserService service, User user) throws RemoteException {
        this.login = login;
        this.service = service;
        this.user = user;
        p = null;
        decimalFormat = new DecimalFormat("¤ #,##0.00");
        initComponents();
        initTables();
        userLabel.setText("Logged on as " + this.user.getName());
        chPwd = new ChangePwdDialog(this, user);
        Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
        //Setting location of login box to center of the screen
        setLocation((d.width - getWidth())/2, (d.height - getHeight())/2);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        searchField = new javax.swing.JTextField();
        articlesLabel = new javax.swing.JLabel();
        articlesScrollPane = new javax.swing.JScrollPane();
        articleTable = new javax.swing.JTable();
        ordersLabel = new javax.swing.JLabel();
        placeOrderButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();
        orderTabPane = new javax.swing.JTabbedPane();
        currentOrderScrollPane = new javax.swing.JScrollPane();
        currentOrderTable = new javax.swing.JTable();
        previousOrdersScrollPane = new javax.swing.JScrollPane();
        previousOrdersTable = new javax.swing.JTable();
        removeButton = new javax.swing.JButton();
        addButton = new javax.swing.JButton();
        totalLabel = new javax.swing.JLabel();
        unitsTextField = new javax.swing.JTextField();
        totalTextField = new javax.swing.JTextField();
        userLabel = new javax.swing.JLabel();
        topMenuBar = new javax.swing.JMenuBar();
        optionsMenu = new javax.swing.JMenu();
        changePwMenu = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        logOutMenu = new javax.swing.JMenuItem();
        exitMenu = new javax.swing.JMenuItem();
        aboutMenu = new javax.swing.JMenu();
        infoMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("User Service");

        searchField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                searchFieldKeyReleased(evt);
            }
        });

        articlesLabel.setText("Articles:");

        articleTable.setModel(articleTableModel);
        articleTable.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                articleTableMouseReleased(evt);
            }
        });
        articlesScrollPane.setViewportView(articleTable);

        ordersLabel.setText("Orders:");

        placeOrderButton.setText("Place Order");
        placeOrderButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                placeOrderButtonActionPerformed(evt);
            }
        });

        cancelButton.setText("Cancel");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });

        orderTabPane.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                orderTabPaneStateChanged(evt);
            }
        });

        currentOrderTable.setModel(currentOrderTableModel);
        currentOrderTable.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                currentOrderTableMouseReleased(evt);
            }
        });
        currentOrderTable.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                currentOrderTablePropertyChange(evt);
            }
        });
        currentOrderScrollPane.setViewportView(currentOrderTable);

        orderTabPane.addTab("Current", currentOrderScrollPane);

        previousOrdersTable.setModel(previousOrdersTableModel);
        previousOrdersScrollPane.setViewportView(previousOrdersTable);

        orderTabPane.addTab("Previous", previousOrdersScrollPane);

        removeButton.setText("Remove");
        removeButton.setToolTipText("");
        removeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeButtonActionPerformed(evt);
            }
        });

        addButton.setText("Add");
        addButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addButtonActionPerformed(evt);
            }
        });

        totalLabel.setText("Total:");

        userLabel.setText("Logged in as ");

        optionsMenu.setText("Options");

        changePwMenu.setText("Change Password");
        changePwMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                changePwMenuActionPerformed(evt);
            }
        });
        optionsMenu.add(changePwMenu);
        optionsMenu.add(jSeparator1);

        logOutMenu.setText("Log Out");
        logOutMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                logOutMenuActionPerformed(evt);
            }
        });
        optionsMenu.add(logOutMenu);

        exitMenu.setText("Exit");
        exitMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuActionPerformed(evt);
            }
        });
        optionsMenu.add(exitMenu);

        topMenuBar.add(optionsMenu);

        aboutMenu.setText("About");

        infoMenuItem.setText("Info");
        infoMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                infoMenuItemActionPerformed(evt);
            }
        });
        aboutMenu.add(infoMenuItem);

        topMenuBar.add(aboutMenu);

        setJMenuBar(topMenuBar);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(addButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(removeButton)
                .addContainerGap(442, Short.MAX_VALUE))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(10, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(orderTabPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 560, Short.MAX_VALUE)
                    .addComponent(articlesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 560, Short.MAX_VALUE))
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addComponent(ordersLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 136, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(434, 434, 434))
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, 112, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 385, Short.MAX_VALUE)
                .addComponent(userLabel)
                .addContainerGap())
            .addGroup(layout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addComponent(articlesLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 210, Short.MAX_VALUE)
                .addGap(360, 360, 360))
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(410, Short.MAX_VALUE)
                .addComponent(placeOrderButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(cancelButton)
                .addContainerGap())
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap(310, Short.MAX_VALUE)
                .addComponent(totalLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(unitsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(totalTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 103, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(20, 20, 20))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(searchField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(userLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(articlesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(articlesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 183, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(removeButton)
                    .addComponent(addButton))
                .addGap(18, 18, 18)
                .addComponent(ordersLabel)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(orderTabPane, javax.swing.GroupLayout.PREFERRED_SIZE, 189, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(totalTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(unitsTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(totalLabel))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cancelButton)
                    .addComponent(placeOrderButton))
                .addContainerGap(14, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void exitMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuActionPerformed
    System.exit(0);
}//GEN-LAST:event_exitMenuActionPerformed

private void searchFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_searchFieldKeyReleased
    search = new ArrayList<>();
    String searchString = searchField.getText().toLowerCase();
    Collection<Article> collection = null;
    try {
        collection = service.getArticles().values();
        for (Article article : collection) {
            if (article.getID().toLowerCase().contains(searchString) || article.getName().toLowerCase().contains(searchString)) {
                search.add(article);
            }
        }
        updateArticleTable(search);
    } catch (RemoteException ex) {
        System.err.println("*** Connection broken. ***");
    }
}//GEN-LAST:event_searchFieldKeyReleased

private void infoMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_infoMenuItemActionPerformed
    showMessageDialog(null, "Made by Anders Hovland & Ole Martinsen");
}//GEN-LAST:event_infoMenuItemActionPerformed

private void logOutMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_logOutMenuActionPerformed
    login.setVisible(true);
    dispose();
}//GEN-LAST:event_logOutMenuActionPerformed

private void changePwMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changePwMenuActionPerformed
    chPwd.setVisible(true);
}//GEN-LAST:event_changePwMenuActionPerformed

private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addButtonActionPerformed
    if (p != null) {
        try {
            int i = articleTable.rowAtPoint(p);
            p = null;
            boolean ok = true;
            String check = (String) articleTableModel.getValueAt(i, 0);
            for (OrderLine line : lines.values()) {
                String like = line.getArticle().getID();
                if(check.equals(like) || service.getArticles().get(like).getStock() == 0)
                    ok = false;
            }
            if (ok) {
                Article a = service.getArticles().get(check);
                OrderLine ol = new OrderLine(a, 1);
                lines.put(ol.getArticle().getID(), ol);
                updateCurrentOrderTable();
                orderTabPane.setSelectedIndex(0);
            }
        } catch (Exception e) {}
    }
}//GEN-LAST:event_addButtonActionPerformed

private void articleTableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_articleTableMouseReleased
    p = new Point(evt.getPoint());
}//GEN-LAST:event_articleTableMouseReleased

private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
    if (p != null) {
        int i = currentOrderTable.rowAtPoint(p);
        p = null;
        String check = (String) currentOrderTableModel.getValueAt(i, 0);
        for (OrderLine ol : lines.values()) {
            String like = ol.getArticle().getID();
            if (check.equals(like)) {
                lines.remove(like);
                updateCurrentOrderTable();
            }
        }
    }
}//GEN-LAST:event_removeButtonActionPerformed

private void currentOrderTableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_currentOrderTableMouseReleased
    p = new Point(evt.getPoint());
}//GEN-LAST:event_currentOrderTableMouseReleased

private void currentOrderTablePropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_currentOrderTablePropertyChange
    if (currentOrderTableModel.getRowCount() != 0) {
        int row = currentOrderTable.getEditingRow();
        try {
            int i = Integer.parseInt((String) currentOrderTableModel.getValueAt(row, 3));
            String check = (String) currentOrderTableModel.getValueAt(row, 0);
            for (OrderLine ol : lines.values()) {
                String like = ol.getArticle().getID();
                if (like.equals(check)) {
                    lines.put(like, new OrderLine(ol.getArticle(), i));
                }
            }
            updateCurrentOrderTable();
        } catch (Exception ex) {
        }
    }
}//GEN-LAST:event_currentOrderTablePropertyChange

private void orderTabPaneStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_orderTabPaneStateChanged
    try {
        int selectedIndex = orderTabPane.getSelectedIndex();
        switch (selectedIndex) {
            case 0:
                updateCurrentOrderTable();
                break;
            case 1:
                updatePreviousOrdersTable();
                break;
        }
    } catch (RemoteException ex) {
    }
}//GEN-LAST:event_orderTabPaneStateChanged

private void placeOrderButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_placeOrderButtonActionPerformed
    if (!lines.isEmpty()) {
        try {
            service.placeOrder(user, lines);
            updatePreviousOrdersTable();
            updateArticleTable(new ArrayList<>(service.getArticles().values()));
            orderTabPane.setSelectedIndex(1);
        } catch (DistSysException ex) {
            showMessageDialog(this, "Unable to place order because " + ex.getMessage());
        } catch (RemoteException ex) {
            showMessageDialog(this, "Unable to place order due to network problems.");
        } finally {
            lines.clear();
            updateCurrentOrderTable();
        }
    }
}//GEN-LAST:event_placeOrderButtonActionPerformed

private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
    lines.clear();
    updateCurrentOrderTable();
}//GEN-LAST:event_cancelButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenu aboutMenu;
    private javax.swing.JButton addButton;
    private javax.swing.JTable articleTable;
    private javax.swing.JLabel articlesLabel;
    private javax.swing.JScrollPane articlesScrollPane;
    private javax.swing.JButton cancelButton;
    private javax.swing.JMenuItem changePwMenu;
    private javax.swing.JScrollPane currentOrderScrollPane;
    private javax.swing.JTable currentOrderTable;
    private javax.swing.JMenuItem exitMenu;
    private javax.swing.JMenuItem infoMenuItem;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JMenuItem logOutMenu;
    private javax.swing.JMenu optionsMenu;
    private javax.swing.JTabbedPane orderTabPane;
    private javax.swing.JLabel ordersLabel;
    private javax.swing.JButton placeOrderButton;
    private javax.swing.JScrollPane previousOrdersScrollPane;
    private javax.swing.JTable previousOrdersTable;
    private javax.swing.JButton removeButton;
    private javax.swing.JTextField searchField;
    private javax.swing.JMenuBar topMenuBar;
    private javax.swing.JLabel totalLabel;
    private javax.swing.JTextField totalTextField;
    private javax.swing.JTextField unitsTextField;
    private javax.swing.JLabel userLabel;
    // End of variables declaration//GEN-END:variables
    
    private void initTables() throws RemoteException {
        articleTable.getTableHeader().setReorderingAllowed(false);
        articleTable.getTableHeader().setResizingAllowed(false);
        currentOrderTable.getTableHeader().setReorderingAllowed(false);
        currentOrderTable.getTableHeader().setResizingAllowed(false);
        previousOrdersTable.getTableHeader().setReorderingAllowed(false);
        previousOrdersTable.getTableHeader().setResizingAllowed(false);
        updateArticleTable(new ArrayList<>(service.getArticles().values()));
        updatePreviousOrdersTable();
    }
    
    private void updateArticleTable(ArrayList<Article> contents) {
        articleTableModel.setRowCount(0);
        
        for (Article a : contents) {
            String ID = a.getID();
            String name = a.getName();
            String price = decimalFormat.format(a.getPrice());
            String stock = "" + a.getStock();
            String pos = a.getPosition().toString();
            articleTableModel.addRow(new String[] {ID, name, price, stock, pos});
        }
    }
    
    private void updateCurrentOrderTable() {
        currentOrderTableModel.setRowCount(0);
        int totalUnits = 0;
        Double totalPrice = 0d;
        
        for (OrderLine ol : lines.values()) {
            String ID = ol.getArticle().getID();
            String name = ol.getArticle().getName();
            String price = decimalFormat.format(ol.getArticle().getPrice());
            int i = ol.getUnits();
            totalUnits += i;
            String units = i + "";
            Double d = ol.getTotal();
            totalPrice += d;
            String total = decimalFormat.format(d);
            currentOrderTableModel.addRow(new String[] {ID, name, price, units, total});
        }
        
        unitsTextField.setText(totalUnits + "");
        totalTextField.setText(decimalFormat.format(totalPrice));
    }
    
    private void updatePreviousOrdersTable() throws RemoteException {
        previousOrdersTableModel.setRowCount(0);
        ArrayList<Order> table = new ArrayList<>(service.getUserOrders(user.getName()).values());
        int totalUnits = 0;
        Double totalPrice = 0d;
        
        for (Order o : table) {
            String ID = "" + o.getOrderID();
            String uName = o.getUser().getName();
            String date = o.getDateString();
            int i = o.getUnits();
            String units = i + "";
            totalUnits += i;
            Double d = o.getTotal();
            String total = decimalFormat.format(d);
            totalPrice += d;
            previousOrdersTableModel.addRow(new String[] {ID, uName, date, units, total});
        }
        
        unitsTextField.setText(totalUnits + "");
        totalTextField.setText(decimalFormat.format(totalPrice));
    }
}